package com.trainfinder.requestor;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Map;

import com.trainfinder.proxy.AbstractService;
import com.trainfinder.proxy.RemoteSocketProvider;
import com.trainfinder.proxy.ServerCreationException;
import com.trainfinder.proxy.Service;
import com.trainfinder.proxy.ServiceProvider;
import com.trainfinder.proxy.ServiceProviderFactory;

public class SimpleServiceFactory implements ServiceProviderFactory {

	private final Service localService;

	private final Service remoteService;

	private final String resourceName;

	private Map tokens;

	public SimpleServiceFactory(String resourceName, Map tokens,
			OutputStream outputSteam) throws ServerCreationException {
		this.resourceName = resourceName;
		this.tokens = tokens;
		localService = new LocalServiceImpl(resourceName, tokens, outputSteam);
		remoteService = newRemoteService();
	}

	private Service newRemoteService() throws ServerCreationException {

		BufferedInputStream in;
		try {
			Service service = new LocalServiceImpl(resourceName, tokens, null);
			in = new BufferedInputStream(service.getInputStream());
		} catch (IOException e) {
			throw new ServerCreationException(e);
		}
		final Socket remoteSocket = new RemoteSocketProvider(in)
				.getRemoteSocket();

		return new AbstractService() {

			public InputStream getInputStream() throws IOException {
				return remoteSocket.getInputStream();
			}

			public OutputStream getOutputStream() throws IOException {
				return remoteSocket.getOutputStream();
			}

		};
	}

	public ServiceProvider newInstance() throws ServerCreationException {

		return new ServiceProvider() {

			public Service getLocalService() {
				return localService;
			}

			public Service getRemoteService() throws ServerCreationException {
				return remoteService;
			}
		};
	}

	public void close() {
		localService.close();
		remoteService.close();
	}

}
